﻿using jp110311.StorageModels;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvcWebRole1.Controllers;
using MvcWebRole1.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace MvcWebRole1.Tests.Controllers
{
    [TestClass]
    public class BbsControllerTest
    {
        public TestContext TestContext { get; set; }


        [TestMethod]
        public void IndexShouldReturnFirstPageWhenPageIsNotPassed()
        {
            // 準備
            var controller = BuildController();

            // 実行
            var result = controller.Index("1234567", null) as ViewResult;

            // アサート
            var model = result.ViewData.Model as BbsAreaIndexModel;
            Assert.AreEqual("1234567", model.ZipCode);
            Assert.AreEqual(1, model.CurrentPage);
            Assert.AreEqual(10, model.PageSize);
            Assert.AreEqual(10, model.Messages.Count);
            for (int i = 0; i < model.Messages.Count; i++)
            {
                Assert.AreEqual(i.ToString(), model.Messages.ElementAt(i).Title);
            }
        }

        [TestMethod]
        public void IndexShouldReturnSpecifiedPage()
        {
            // 準備
            var controller = BuildController();

            // 実行
            var result = controller.Index("1234567", 1) as ViewResult;

            // アサート
            var model = result.ViewData.Model as BbsAreaIndexModel;
            Assert.AreEqual("1234567", model.ZipCode);
            Assert.AreEqual(1, model.CurrentPage);
            Assert.AreEqual(10, model.PageSize);
            Assert.AreEqual(10, model.Messages.Count);
            Assert.AreEqual(90, model.Total);
            for (int i = 0; i < model.Messages.Count; i++)
            {
                Assert.AreEqual((i).ToString(), model.Messages.ElementAt(i).Title);
            }
        }

        [TestMethod]
        public void SearchShouldReturnFirstPageWhenPageIsNotPassed()
        {
            // 準備
            var controller = BuildController();

            // 実行
            var result = controller.Search("1234567", "abc", null) as ViewResult;

            // アサート
            var model = result.ViewData.Model as BbsAreaIndexModel;
            Assert.AreEqual("1234567", model.ZipCode);
            Assert.AreEqual("abc", model.Tag);
            Assert.AreEqual(1, model.CurrentPage);
            Assert.AreEqual(10, model.PageSize);
            Assert.AreEqual(10, model.Messages.Count);
            Assert.AreEqual(45, model.Total);
            for (int i = 0; i < model.Messages.Count; i++)
            {
                Assert.AreEqual((i * 2).ToString(), model.Messages.ElementAt(i).Title);
            }
        }

        [TestMethod]
        public void SearchShouldReturnSpecifiedPage()
        {
            // 準備
            var controller = BuildController();

            // 実行
            var result = controller.Search("1234567", "abc", 1) as ViewResult;

            // アサート
            var model = result.ViewData.Model as BbsAreaIndexModel;
            Assert.AreEqual("1234567", model.ZipCode);
            Assert.AreEqual("abc", model.Tag);
            Assert.AreEqual(1, model.CurrentPage);
            Assert.AreEqual(10, model.PageSize);
            Assert.AreEqual(10, model.Messages.Count);
            for (int i = 0; i < model.Messages.Count; i++)
            {
                Assert.AreEqual((i * 2 ).ToString(), model.Messages.ElementAt(i).Title);
            }
        }

        private BbsController BuildController()
        {
            var controller = new BbsController(new MockBbsEntityServiceInvoker());
            return controller;
        }


        // テストのためにBbsEntityServicesの処理をエミュレートするクラス。
        private class MockBbsEntityServiceInvoker : BbsController.IBbsEntityServiceInvoker
        {
            private List<BbsEntity> entities;

            public MockBbsEntityServiceInvoker()
            {
                entities = new List<BbsEntity>();
                for (int i = 0; i < 10; i++) entities.Add(new BbsEntity { PartitionKey = "0000000", Title = i.ToString() });
                for (int i = 0; i < 90; i++) entities.Add(new BbsEntity { PartitionKey = "1234567", Title = i.ToString() });
                for (int i = 0; i < 20; i++) entities.Add(new BbsEntity { PartitionKey = "9999999", Title = i.ToString() });
                for (int i = 0; i < entities.Count; i += 2) entities[i].TagList = "abc";
            }

            public IEnumerable<BbsEntity> GetBbsEntities(string zipCode, int skipCount, int maxCount)
            {
                return entities.Where(o => o.PartitionKey == zipCode).Where((o, i) => skipCount <= i && i < skipCount + maxCount);
            }

            public IEnumerable<BbsEntity> GetBbsEntityByTag(string zipCode, string tag, int skipCount, int maxCount)
            {
                return entities.Where(o => o.PartitionKey == zipCode && o.TagList == tag).Where((o, i) => skipCount <= i && i < skipCount + maxCount);
            }

            public int GetBbsEntitiesCount(string zipCode)
            {
                return entities.Count(o => o.PartitionKey == zipCode);
            }

            public int GetBbsTagedEntitiesCount(string zipCode, string tag)
            {
                return entities.Count(o => o.PartitionKey == zipCode && o.TagList == tag);
            }

            public IEnumerable<BbsTagEntity> GetBbsTags(string zipCode, int skipCount, int maxCount)
            {
                throw new NotImplementedException();
            }

            public string AddBbsMessage(string zipCode, DateTime postAt, string title, string content, string authorZipCode, string authorNick)
            {
                throw new NotImplementedException();
            }

            public string AddBbsMessage(string zipCode, DateTime postAt, string title, string content, string authorZipCode, string authorNick, string tag)
            {
                throw new NotImplementedException();
            }

            public void AddTagToBbsEntity(string zipCode, string bbsMsgId, string tag)
            {
                throw new NotImplementedException();
            }

            public void RemoveTagFromBbsEntity(string zipCode, string bbsMsgId, string tag)
            {
                throw new NotImplementedException();
            }
        }
    }
}
